unit DownloadController;

interface

  uses
    AbstractController, IEDownload, Windows, Classes;

  type
    TDownloadThread = class(TThread)
      protected
        DownloadPointer : procedure() of object;
        procedure Execute(); override;
    end;
    TDownloadController = class(TController)
      private
        fDownloadThread : TDownloadThread;
        fPath : Widestring;
        fIED : TIEDownload;
        fCurrent, fMax : Cardinal;
        fRunning, fFinished, fError : Boolean;
        procedure SetOptions();
        procedure DownloadError(const ErrorCode: integer; const stError: string);
        procedure DownloadProgress(Sender: TBSCB; ulProgress, ulProgressMax, ulStatusCode, FileSize: ULONG; szStatusText: LPCWSTR; Downloaded, ElapsedTime, Speed, RemainingTime, Status, Percent: string);
        procedure DownloadFinished(Sender: TCustomIEDownload; aFileNameAndPath, aFileName, aFolderName, aExtension: WideString; const ActiveConnections : Integer);
        procedure Download();
      protected
        function GetCurrent : Cardinal; override;
        function GetMax() : Cardinal; override;
        function GetRunning() : Boolean; override;
        function GetFinished() : Boolean; override;
        function GetError() : Boolean; override;
      published
        procedure Toggle(); override;
        procedure Cancel(); override;
        property Finished : Boolean read fFinished;
        property Error : Boolean read fError;
        constructor Create(Path : Widestring);
    end;

implementation

  uses
    Dialogs, SysUtils, StringUtils;

  function TDownloadController.GetCurrent() : Cardinal;
  begin
    Result := fCurrent;
  end;

  function TDownloadController.GetMax() : Cardinal;
  begin
    Result := fMax;
  end;

  function TDownloadController.GetRunning() : Boolean;
  begin
    Result := fRunning;
  end;

  function TDownloadController.GetFinished() : Boolean;
  begin
    Result := fFinished;
  end;

  function TDownloadController.GetError() : Boolean;
  begin
    Result := fError;
  end;

  procedure TDownloadController.DownloadError(const ErrorCode: integer; const stError: string);
  begin
    if fFinished = true then fError := true;
  end;

  procedure TDownloadController.DownloadProgress(Sender: TBSCB; ulProgress, ulProgressMax, ulStatusCode, FileSize: ULONG; szStatusText: LPCWSTR; Downloaded, ElapsedTime, Speed, RemainingTime, Status, Percent: string);
  begin
    fRunning := true;
    fCurrent := ulProgress;
    fMax := ulProgressMax;
  end;

  procedure TDownloadController.DownloadFinished(Sender: TCustomIEDownload; aFileNameAndPath, aFileName, aFolderName, aExtension: WideString; const ActiveConnections : Integer);
  begin
    fFinished := true;
    fRunning := false;
  end;

  procedure TDownloadController.SetOptions();
  begin
    try
      if fIED <> nil then
      begin
        fIED.OnError := DownloadError;
        fIED.OnProgress := DownloadProgress;
        fIED.OnComplete := DownloadFinished;
        fIED.DownloadMethod := dmFile;
        {fIED.BindF := [
          Asynchronous, AsyncStorage, GetNewestVersion, NoWriteCache, NeedFile,
          Resynchronize, PullData, Pragma_No_Cache, No_UI, SilentOperation,
          PreferDefaultHandler, FromUrlMon
        ];}
        fIED.BindF := [
          Asynchronous, AsyncStorage, GetNewestVersion, NoWriteCache, PullData
        ];
        //fIED.CodePage := UTF8;
        fIED.DownloadFolder := GetCurrentDir + '\Downloads';
      end;
    except end;
  end;

  procedure TDownloadController.Download();
  begin
    //showmessage(GetCurrentDir + '\' + ExtractUrlFilename(fPath));
    //fIED.Go(fPath, GetCurrentDir + '\' + ExtractUrlFilename(fPath));
    fIED.Go(fPath);
  end;

  //****************************************************************************
  // Published
  //****************************************************************************

  procedure TDownloadController.Toggle();
  begin
    try
      if fIED <> nil then
      begin
        if fIED.State <> sStopped then
        begin
          fIED.Suspend();
          fRunning := false;
        end else
        begin
          fIED.Resume();
          fRunning := true;
        end;
      end;
    except end;
  end;

  procedure TDownloadController.Cancel();
  begin
    try
      if fIED <> nil then
        fIED.CancelAll;
    except end;
  end;

  constructor TDownloadController.Create(Path: WideString);
  begin
    fPath := Path;
    fIED := TIEDownload.Create(nil);
    SetOptions();
    fDownloadThread := TDownloadThread.Create(True);
    fDownloadThread.DownloadPointer := Download;
    fDownloadThread.Priority := tpLowest; //TThreadPriority
    fDownloadThread.Resume();
    fRunning := true;
  end;

  procedure TDownloadThread.Execute();
  begin
    Synchronize(DownloadPointer);
  end;

end.
